
/**
\file
Definition of the rainbow::viewport_stack class.
\author Sean Tromans
*/

#ifndef	RAINBOW_VIEWPORT_STACK_HPP
#define	RAINBOW_VIEWPORT_STACK_HPP

#include <rainbow/viewport/viewport_fwd.hpp>
#include <rainbow/exception/exception.hpp>
#include <sun/lua/lua_fwd.hpp>
#include <vector>
#include <queue>

namespace rainbow
{

	/**
	Exception thrown if a null viewport is pushed onto the stack.
	\author Sean Tromans
	*/
	class null_viewport : public exception
	{
	public:

		null_viewport( )
			:	exception( nmn::create_string( "rainbow::null_viewport: Attempted to add a null viewport to the viewport_stack." )  )
		{ }
	};

	/**
	Contains all the viewports to be drawn this frame.
	\note
		Viewports are drawn in stack order (LIFO) although their render queues are built in queue order (FIFO).
		This is to easily manage the dependencies of which viewports rely on other viewports.
		e.g. A viewport placed on the stack will begin generating its render queue. It will discover that to be drawn correctly
		a light needs to have its shadow map redrawn. This will add a new vieport to the queue which will be drawn before the first viewport.
		All that this means in practice is that a viewport needs to be drawn on top of another, it should be placed on the stack before hand.
		Picture-in-picture, GUI/HUD, Main Viewport etc.
	\author Sean Tromans
	*/
	class viewport_stack
	{
		//
		//	Public Member Functions
		//
		public:

			/**
			Push a new viewport onto the stack to be drawn.
			\note
				Can safetly be called while drawing. Will result in the new vp being drawn before any current vp's.
			@param vp The new viewport to add.
			\author Sean Tromans
			*/
			void push( viewport_ptr vp );

			/**
			Build all viewport render queues and then begin drawing.
			\note
				This will also clear the stack of any viewports.
			@param step_fraction How far between logic updates this frame is.
			\author Sean Tromans
			*/
			void draw( float step_fraction );

		//
		//	Private Member Types
		//
		private:

			/** A queue of viewports waiting to have their render queues built. */
			typedef	std::queue< viewport_ptr > enqueued_viewports_t;

			/**
			A collection of viewports ready to be drawn.
			Required to be a vector because of the need to remove duplicate viewports ad place higher up the stack.
			Also requires reverse iteration when drawing.
			*/
			typedef	std::vector< viewport_ptr > stacked_viewports_t;

		//
		//	Private Member Variables
		//
		private:

			enqueued_viewports_t	m_queue;	///< The currently queued viewports waiting to have their render queues built.
			stacked_viewports_t		m_stack;	///< Viewports with render queues ready to be drawn in the order they were added to the viewport_queue.

		//
		//	Static Member Functions.
		//
		public:

			/**
			Exposes the viewport_stack to lua.
			@param L The Lua State being initialised.
			\author Sean Tromans.
			*/
			static void lua_interface( lua_State * L );
	};

};

#endif	//RAINBOW_VIEWPORT_STACK_HPP